Do not deadlock in scheduler when sending VIRQ_CON_RING.
authorKeir Fraser <keir.fraser@citrix.com>
Fri, 6 Mar 2009 14:28:27 +0000 (14:28 +0000)
committerKeir Fraser <keir.fraser@citrix.com>
Fri, 6 Mar 2009 14:28:27 +0000 (14:28 +0000)
Instead defer the virq notification to tasklet context.

Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
xen/drivers/char/console.c

index 3096b3ec9d27c3a6aca8da7a5a1f6b23070740c7..00a32022dd3d4e94e0fd290c10dcdd022db34132 100644 (file)
@@ -315,6 +315,12 @@ static void serial_rx(char c, struct cpu_user_regs *regs)
     __serial_rx(c, regs);
 }
 
+static void notify_dom0_con_ring(unsigned long unused)
+{
+    send_guest_global_virq(dom0, VIRQ_CON_RING);
+}
+static DECLARE_TASKLET(notify_dom0_con_ring_tasklet, notify_dom0_con_ring, 0);
+
 static long guest_console_write(XEN_GUEST_HANDLE(char) buffer, int count)
 {
     char kbuf[128], *kptr;
@@ -348,7 +354,7 @@ static long guest_console_write(XEN_GUEST_HANDLE(char) buffer, int count)
         {
             for ( kptr = kbuf; *kptr != '\0'; kptr++ )
                 putchar_console_ring(*kptr);
-            send_guest_global_virq(dom0, VIRQ_CON_RING);
+            tasklet_schedule(&notify_dom0_con_ring_tasklet);
         }
 
         spin_unlock_irq(&console_lock);
@@ -426,7 +432,7 @@ static void __putstr(const char *str)
     while ( (c = *str++) != '\0' )
         putchar_console_ring(c);
 
-    send_guest_global_virq(dom0, VIRQ_CON_RING);
+    tasklet_schedule(&notify_dom0_con_ring_tasklet);
 }
 
 static int printk_prefix_check(char *p, char **pp)